#!coding:utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
from rest_framework import status
from cvirt.common import translate as _
from django.db import transaction
from cvirt.tasks.vm import apply_sgroup, update_sgroup, remove_sgroup
import netaddr
from cvirt.manager.serializers import SecurityGroupIngressRuleSerializer, SecurityGroupSerializer
from cvirt.manager.views import BaseRetriveAPIView, NamedAPIViewMixIn
from rest_framework.response import Response
from cvirt.manager.models import SecurityGroupIngressRule, SecurityGroup, Interface, Server


class SecurityRuleView(NamedAPIViewMixIn, BaseRetriveAPIView):
    model = SecurityGroupIngressRule
    serializer_class = SecurityGroupIngressRuleSerializer


    def _get(self,request, *args, **kwargs):
        dataset = None
        group_id = request.GET.get("group")
        if group_id:
            group = SecurityGroup.objects.get_or_none(id=group_id)
            dataset = SecurityGroupIngressRule.objects.filter(group=group)
        else:
            dataset = SecurityGroupIngressRule.objects.all()
        result = self.paginate(request, dataset, SecurityGroupIngressRuleSerializer)
        return Response(result)


    @transaction.commit_on_success
    def create(self, request, *args, **kwargs):

        securityRule = request.DATA.get("securityrule", None)

        if securityRule:
            protocol = securityRule.get("protocol", None)
            protocolValue = protocol.get("value")

            priority = securityRule.get("priority", 0)

            direction = securityRule.get("direction", None)
            directionValue = None
            if direction:
                directionValue = direction.get("value")

            dstipfrom = securityRule.get("dstipfrom", None)
            dstipto = securityRule.get("dstipto", None)

            dstportstart = securityRule.get("dstportstart", None)
            dstportend = securityRule.get("dstportend", None)

            if dstipfrom and dstipto:
                ip1 = netaddr.IPAddress(dstipfrom)
                ip2 = netaddr.IPAddress(dstipto)

                # 将大的IP作为to
                if ip1 > ip2:
                    dstipto,dstipfrom = dstipfrom,dstipto

            srcipfrom = None
            srcipto = None
            srcportstart = None
            srcportend = None

            if cmp(directionValue, "inout") == 0:
                srcipfrom = dstipfrom
                srcipto = dstipto
                srcportstart = dstportstart
                srcportend = dstportend

            group = None
            group_id = securityRule.get("group").get("value")
            if group_id:
                group = SecurityGroup.objects.get(id=group_id)

            rule = SecurityGroupIngressRule.objects.create(protocol=protocolValue, priority=priority, direction=directionValue,
                                                dstipfrom=dstipfrom, dstipto=dstipto, dstportstart=dstportstart,
                                                dstportend=dstportend, srcipfrom=srcipfrom, srcipto=srcipto,
                                                srcportstart=srcportstart, srcportend=srcportend, group=group,action='accept')
            update_sgroup.boadcast(group)

            #return Response({"result":"ok"})
            return Response(self.get_serializer(rule).data, 200)

        #return Response({"result":"error"})
        return Response("security rule can not be null", 400)

    @transaction.commit_on_success
    def update(self, request, *args, **kwargs):

        securityRule = request.DATA.get("securityrule", None)

        if securityRule:
            protocol = securityRule.get("protocol", None)

            protocolValue = None
            if protocol:
                protocolValue = protocol.get("value")

            priority = securityRule.get("priority", 0)

            direction = securityRule.get("direction", None)
            directionValue = None
            if direction:
                directionValue = direction.get("value")

            dstipfrom = securityRule.get("dstipfrom", None)
            dstipto = securityRule.get("dstipto", None)

            dstportstart = securityRule.get("dstportstart", None)
            dstportend = securityRule.get("dstportend", None)

            srcipfrom = None
            srcipto = None
            srcportstart = None
            srcportend = None

            if cmp(directionValue, "inout") == 0:
                srcipfrom = dstipfrom
                srcipto = dstipto
                srcportstart = dstportstart
                srcportend = dstportend

            group = None
            group_id = securityRule.get("group").get("value")
            if group_id:
                group = SecurityGroup.objects.get(id=group_id)

            securityGroupIngressRule = SecurityGroupIngressRule.objects.get_or_none(id=securityRule.get('id'))
            securityGroupIngressRule.update(dict(protocol=protocolValue, priority=priority, direction=directionValue,
                                             dstipfrom=dstipfrom, dstipto=dstipto, dstportstart=dstportstart,
                                             dstportend=dstportend, srcipfrom=srcipfrom, srcipto=srcipto,
                                             srcportstart=srcportstart, srcportend=srcportend, group=group))
            update_sgroup.boadcast(group)

            #return Response({"result":"ok"})
            return Response(self.get_serializer(securityGroupIngressRule).data, 200)

        #return Response({"result":"error"})
        return Response("security rule can not be null", 400)

    @transaction.commit_on_success
    def delete_all(self, request, *args, **kwargs):

        ids = request.DATA.get('ids')
        sgroup = SecurityGroupIngressRule.objects.get(id=ids[0]).group
        for id in ids:
            SecurityGroupIngressRule.objects.get(id=id).delete()

        update_sgroup.boadcast(sgroup)

        return self._get(request, args, kwargs)



class SecurityGroupView(NamedAPIViewMixIn, BaseRetriveAPIView):
    model = SecurityGroup
    serializer_class = SecurityGroupSerializer


    def _get(self,request, *args, **kwargs):
        dataset = SecurityGroup.objects.all()
        result = self.paginate(request, dataset, SecurityGroupSerializer)
        return Response(result)


    def create(self, request, *args, **kwargs):

        securityGroup = request.DATA.get("securitygroup", None)

        if securityGroup:
            name = securityGroup.get("name")

            description = securityGroup.get("description", None)

            #避免重复插入数据
            if not SecurityGroup.objects.filter(name=name):
                group = SecurityGroup.objects.create(name=name, description=description)
            else:
                return Response(_('规则组%s已存在'% name), status.HTTP_400_BAD_REQUEST)

            #return Response({"result":"ok"})
            return Response(self.get_serializer(group).data, 200)

        #return Response({"result":"error"})
        return Response("security group can not be null", 400)


    def update(self, request, *args, **kwargs):

        securityGroup = request.DATA.get("securitygroup", None)

        if securityGroup:
            # name = securityGroup.get("name")

            description = securityGroup.get("description", None)

            securityGroupEntity = SecurityGroup.objects.get_or_none(id=securityGroup.get('id'))
            securityGroupEntity.update(dict(description=description))

            #return Response({"result":"ok"})
            return Response(self.get_serializer(securityGroupEntity).data, 200)

        #return Response({"result":"error"})
        return Response("security group can not be null", 400)

    @transaction.commit_on_success
    def delete_all(self, request, *args, **kwargs):

        ids = request.DATA.get('ids')
        for id in ids:
            sgroup = SecurityGroup.objects.get(id=id)
            if sgroup:
                #记录之前关联的网卡id
                interfaces = [iface.id for iface in sgroup.interface_set.all()]
                #解除关联
                sgroup.update(dict(interface_set=[]))

                remove_sgroup.boadcast(sgroup,interfaces)
                #在cnode上做delete操作
        return Response(status=200)

    @transaction.commit_on_success
    def relate_vm(self, request, *args, **kwargs):

        security_group_id = request.DATA.get("id")
        security_group = SecurityGroup.objects.get_or_none(id=security_group_id)

        ids = request.DATA.get("interface_ids")

        interfaces = set([])

        #这里要获取id，如果直接使用model。下面对group的修改会影响已经获取的值
        oldifaces = [iface.id for iface in security_group.interface_set.all()]

        for id in ids:
            interface = Interface.objects.get(id=id)
            interfaces.add(interface)

        security_group.interface_set = interfaces
        security_group.save()

        apply_sgroup.boadcast(security_group,oldifaces)

        return Response({"result":"ok"})




